<script setup lang="ts">
import type { UploadChangeParam, UploadFile } from 'ant-design-vue';

import type { PropType } from 'vue';

import { computed, ref, useAttrs, watch } from 'vue';

import { useAccessStore } from '@vben/stores';

import { Button, message, Upload } from 'ant-design-vue';

import { Icon } from '#/components/icon';
import { omit } from '#/util/tool';

defineOptions({
  name: 'Upload',
  inheritAttrs: false,
});
const props = defineProps({
  modelValue: {
    // 图片URL
    type: [String] as PropType<string>,
    default: undefined,
  },
  action: {
    // 上传的地址
    type: String,
    default: `${import.meta.env.VITE_GLOB_API_URL}/file/upload/url`,
  },
  headers: {
    // 上传请求的 headers
    type: Object,
    default: () => ({}),
  },
  disabled: {
    // 是否禁用
    type: Boolean,
    default: false,
  },
  listType: {
    // 上传类型
    type: String as PropType<'picture' | 'picture-card' | 'text'>,
    default: 'picture-card',
  },
  uploadName: {
    // 文件上传字段名,name被字段名覆写了，要换成uploadName
    type: String,
    default: undefined,
  },
});
const emits = defineEmits(['update:modelValue']);
const accessStore = useAccessStore();
const fileList = ref<UploadFile[]>([]);
const attrs = useAttrs();
const bindProps = computed(() => {
  return {
    ...omit(attrs, ['onChange', 'onInput', 'onBlur', 'name']),
    ...props,
    name: props.uploadName || 'file',
  };
});

const mValue = computed({
  get() {
    return props.modelValue;
  },
  set(val) {
    emits('update:modelValue', val);
  },
});
const mHeaders = {
  Authorization: `Bearer ${accessStore.accessToken}`,
  ...props.headers,
};

const handleChange = (info: UploadChangeParam) => {
  if (info.file.status === 'done') {
    try {
      // 获取上传后的图片URL
      const response = info.file.response || {};
      const data = response.data || {};

      // 尝试从不同的响应结构中获取URL
      let imageUrl = '';
      if (data.url) {
        imageUrl = data.url;
      } else if (data.imageUrl) {
        imageUrl = data.imageUrl;
      } else if (typeof response === 'string') {
        // 有些API可能直接返回URL字符串
        imageUrl = response;
      } else if (typeof data === 'string') {
        // 或者data直接是URL字符串
        imageUrl = data;
      }

      if (imageUrl) {
        // 更新文件列表
        fileList.value = [
          {
            uid: info.file.uid,
            name: info.file.name,
            status: 'done',
            url: imageUrl,
          },
        ];

        // 更新模型值并触发事件通知父组件
        emits('update:modelValue', imageUrl);

        message.success('图片上传成功');
      } else {
        message.error('上传图片失败，未获取到图片URL');
        console.error('上传响应中未找到图片URL:', response);
      }
    } catch (error) {
      message.error('处理上传响应时发生错误');
      console.error('上传响应处理错误:', error);
    }
  } else if (info.file.status === 'error') {
    message.error(`${info.file.name} 图片上传失败`);
    console.error('上传错误:', info.file.error);
  }
};

const handleRemove = () => {
  fileList.value = [];
  mValue.value = '';
  return true;
};

// 初始化时，如果已有值（URL），则显示该图片
watch(
  () => props.modelValue,
  (val) => {
    fileList.value = val
      ? [
          {
            uid: '-1',
            name: '图片',
            status: 'done',
            url: val,
          },
        ]
      : [];
  },
  { immediate: true },
);
</script>
<template>
  <Upload
    v-model:file-list="fileList"
    v-bind="bindProps"
    :action="action"
    :disabled="disabled"
    :headers="mHeaders"
    :list-type="listType"
    :max-count="1"
    accept="image/*"
    @change="handleChange"
    @remove="handleRemove"
  >
    <template #default>
      <div v-if="fileList.length === 0">
        <Icon
          v-if="listType === 'picture-card'"
          :size="24"
          icon="ant-design:plus-outlined"
        />
        <Button v-else>
          上传图片
          <template #icon>
            <Icon icon="ant-design:upload-outlined" />
          </template>
        </Button>
      </div>
    </template>
    <template v-for="item in Object.keys($slots)" #[item]="data">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </Upload>
</template>
